package org.wikipedia.miner.service;

import java.sql.SQLException;

import org.w3c.dom.*;

import org.wikipedia.miner.model.*;

/**
 * @author Stephen Remde
 * 
 * <p>This service provides information needed for and A* search for a page ids. </p>
 *  
 */
public class AStar {

	private WikipediaMinerServlet wms ;
		
	private int defaultMaxLinkCount = 250 ;
	private int defaultMaxSenseCount = 25 ;

	/**
	 * @param wms the servlet that hosts this service
	 */
	public AStar(WikipediaMinerServlet wms) {
		this.wms = wms ;
	}
	
	/**
	 * @return the default number of links that are shown extending out from and into Wikipedia pages. 
	 */
	public int getDefaultMaxLinkCount() {
		return defaultMaxLinkCount ;
	}
	
	/**
	 * @return the default number of senses that will be shown for an ambiguous term. 
	 */
	public int getDefaultMaxSenseCount() {
		return defaultMaxSenseCount ;
	}
	
	/**
	 * @return an Element description of this service; what it does, and what parameters it takes.
	 */
	public Element getDescription() {
		
		Element description = wms.doc.createElement("Description") ;
		description.setAttribute("task", "astar") ;
		
		description.appendChild(wms.createElement("Details", "<p>This service provides information needed for and A* search for a page ids. </p>")) ;
			
		Element group2 = wms.doc.createElement("ParameterGroup") ;
		description.appendChild(group2) ;
		
		Element paramId = wms.doc.createElement("Parameter") ;
		paramId.setAttribute("name", "id") ;
		paramId.appendChild(wms.doc.createTextNode("The unique identifier of the page to search for.")) ;
		group2.appendChild(paramId) ;
		
		Element paramLinkCount = wms.doc.createElement("Parameter") ;
		paramLinkCount.setAttribute("name", "maxLinkCount") ;
		paramLinkCount.appendChild(wms.doc.createTextNode("The maximum number of page links or child categories and articles to return when presenting the details of an article or category.")) ;
		paramLinkCount.setAttribute("optional", "true") ;
		paramLinkCount.setAttribute("default", String.valueOf(getDefaultMaxLinkCount())) ; 
		description.appendChild(paramLinkCount) ;
		
		Element paramSenseCount = wms.doc.createElement("Parameter") ;
		paramSenseCount.setAttribute("name", "maxSenseCount") ;
		paramSenseCount.appendChild(wms.doc.createTextNode("The maximum number of senses to return when given an ambiguous term.")) ;
		paramSenseCount.setAttribute("optional", "true") ;
		paramSenseCount.setAttribute("default", String.valueOf(getDefaultMaxSenseCount())) ; 
		description.appendChild(paramSenseCount) ;
		
		return description ;
	}
	
	

	/**
	 * @param id the id of the page to search for
	 * @param linkLimit the maximum number of links to show extending out from and into the target page.
	 * @return Element details of the page defined by id.
	 * @throws Exception
	 */
	public Element doSearch(int id, int destination, int linkLimit) throws Exception {
		
		Element response = wms.doc.createElement("SearchResponse") ;
		
		Page page = wms.wikipedia.getPageById(id) ;
		Page page2 = wms.wikipedia.getPageById(destination) ;
		
		
		
		if (page != null) {
			
			response.setAttribute("term", page.getTitle()) ;
			
			switch (page.getType()) {
			
			case Page.ARTICLE :
				response.appendChild(getArticleDetails(page, page2, linkLimit)) ;
				break ;			
			}
		}
		
		return response ;
	}
	
	private Element getArticleDetails(Page page, Page page2, int linkLimit) throws SQLException{
		
		Article article = (Article)page ;
		Article article2 = (Article)page2 ;
		
		Element xmlArt = wms.doc.createElement("Article") ;
		
		xmlArt.setAttribute("id", String.valueOf(article.getId())) ;
		xmlArt.setAttribute("title", article.getTitle()) ;
		//xmlArt.setAttribute("description", getDescription(article)) ;
		
		
		int[] linksOut = article.getLinksOutIds() ;
		
		if (linksOut.length > 0) {
			
			Element xmlLinks = wms.doc.createElement("LinkOutList") ;


			int count = 0 ;
			
			for (int id: linksOut) {
				if (count++ == linkLimit) break ;
				
				try {
					Article link = new Article(wms.wikipedia.getDatabase(), id) ;	
				
					Element xmlLink = wms.doc.createElement("LinkOut") ;
				
					xmlLink.setAttribute("id", String.valueOf(link.getId())) ;
					xmlLink.setAttribute("title", link.getTitle()) ;
					xmlLink.setAttribute("relatedness", wms.df.format(link.getRelatednessTo(article))) ;
					xmlLink.setAttribute("relatednessdest", 
							wms.df.format(link.getRelatednessTo(article2))) ;
										
					xmlLinks.appendChild(xmlLink) ;
				} catch (Exception e) {} ;
			}
			xmlArt.appendChild(xmlLinks) ;
		}
		
		int[] linksIn = article.getLinksInIds() ;
		
		if (linksIn.length > 0) {
			
			Element xmlLinks = wms.doc.createElement("LinkInList") ;
			xmlLinks.setAttribute("size", String.valueOf(linksIn.length)) ;
			int count = 0 ;
			
			for (int id: linksIn) {
				if (count++ == linkLimit) break ;
				
				try {
					Article link = new Article(wms.wikipedia.getDatabase(), id) ;	
				
					Element xmlLink = wms.doc.createElement("LinkIn") ;
				
					xmlLink.setAttribute("id", String.valueOf(link.getId())) ;
					xmlLink.setAttribute("title", link.getTitle()) ;
					xmlLink.setAttribute("relatedness", wms.df.format(link.getRelatednessTo(article))) ;
					xmlLink.setAttribute("relatednessdest", 
							wms.df.format(link.getRelatednessTo(article2))) ;
					
					xmlLinks.appendChild(xmlLink) ;
				} catch (Exception e) {} ;
			}
			xmlArt.appendChild(xmlLinks) ;
		}
			
		return xmlArt ;
	}
	
	
	
		
	
}
